extends layout

append style
  link(rel="stylesheet", href="/docs/css/inlinecpc.css")
  script(type="text/javascript" src="/docs/js/native.js")

block append style
  style.
    hr {
      display: block;
      margin-top: 40px;
      margin-bottom: 40px;
      border: 0px;
      height: 1px;
      background-color: #232323;
      width: 100%;
    }

block content
  :markdown
    ## FAQ

    <script>
      _native.init("CK7DT53U",{
        targetClass: 'native-inline'
      });
    </script>

    <div class="native-inline">
      <a href="#native_link#"><span class="sponsor">Sponsor</span> #native_company# — #native_desc#</a>
    </div>

    **Q**. Why don't my changes to arrays get saved when I update an element
    directly?

    ```javascript
    doc.array[3] = 'changed';
    doc.save();
    ```

    **A**. Mongoose doesn't create getters/setters for array indexes; without
    them mongoose never gets notified of the change and so doesn't know to
    persist the new value. The work-around is to use
    [MongooseArray#set](./api.html#types_array_MongooseArray.set) available
    in **Mongoose >= 3.2.0**.

    ```javascript
    // 3.2.0
    doc.array.set(3, 'changed');
    doc.save();

    // if running a version less than 3.2.0, you must mark the array modified before saving.
    doc.array[3] = 'changed';
    doc.markModified('array');
    doc.save();
    ```

    <hr id="unique-doesnt-work" />

    **Q**. I declared a schema property as `unique` but I can still save
    duplicates. What gives?

    **A**. Mongoose doesn't handle `unique` on its own: `{ name: { type: String, unique: true } }`
    is just a shorthand for creating a [MongoDB unique index on `name`](https://docs.mongodb.com/manual/core/index-unique/).
    For example, if MongoDB doesn't already have a unique index on `name`, the below code will not error despite the fact that `unique` is true.

    ```javascript
    var schema = new mongoose.Schema({
      name: { type: String, unique: true }
    });
    var Model = db.model('Test', schema);

    Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
      console.log(err); // No error, unless index was already built
    });
    ```

    However, if you wait for the index to build using the `Model.on('index')` event, attempts to save duplicates will correctly error.

    ```javascript
    var schema = new mongoose.Schema({
      name: { type: String, unique: true }
    });
    var Model = db.model('Test', schema);

    Model.on('index', function(err) { // <-- Wait for model's indexes to finish
      assert.ifError(err);
      Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
        console.log(err);
      });
    });

    // Promise based alternative. `init()` returns a promise that resolves
    // when the indexes have finished building successfully. The `init()`
    // function is idempotent, so don't worry about triggering an index rebuild.
    Model.init().then(function() {
      assert.ifError(err);
      Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
        console.log(err);
      });
    });
    ```

    MongoDB persists indexes, so you only need to rebuild indexes if you're starting
    with a fresh database or you ran `db.dropDatabase()`. In a production environment,
    you should [create your indexes using the MongoDB shell])(https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/)
    rather than relying on mongoose to do it for you. The `unique` option for schemas is
    convenient for development and documentation, but mongoose is *not* an index management solution.

    <hr id="nested-properties" />

    **Q**. When I have a nested property in a schema, mongoose adds empty objects by default. Why?

    ```javascript
    var schema = new mongoose.Schema({
      nested: {
        prop: String
      }
    });
    var Model = db.model('Test', schema);

    // The below prints `{ _id: /* ... */, nested: {} }`, mongoose assigns
    // `nested` to an empty object `{}` by default.
    console.log(new Model());
    ```

    **A**. This is a performance optimization. These empty objects are not saved
    to the database, nor are they in the result `toObject()`, nor do they show
    up in `JSON.stringify()` output unless you turn off the [`minimize` option](./guide.html#minimize).

    The reason for this behavior is that Mongoose's change detection
    and getters/setters are based on [`Object.defineProperty()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).
    In order to support change detection on nested properties without incurring
    the overhead of running `Object.defineProperty()` every time a document is created,
    mongoose defines properties on the `Model` prototype when the model is compiled.
    Because mongoose needs to define getters and setters for `nested.prop`, `nested`
    must always be defined as an object on a mongoose document, even if `nested`
    is undefined on the underlying [POJO](./guide.html#minimize).

    <hr id="destructured-imports" />

    **Q**. When I use destructuring imports like `import { model } from 'mongoose'`, I get an error:

    ```
    TypeError: Cannot read property 'modelSchemas' of undefined
    ```

    What causes this issue and how can I fix it?

    **A**. The only import syntax Mongoose supports is `import mongoose from 'mongoose'`.
    Syntaxes like `import * from 'mongoose'` or `import { model } from 'mongoose'` do **not** work.
    The global Mongoose object stores types, [global options](/docs/api.html#mongoose_Mongoose-set), and other important
    properties that Mongoose needs. When you do `import { model } from 'mongoose'`, the
    `this` value in `model()` is not the Mongoose global.

    ```javascript
    // file1.js
    exports.answer = 42;
    exports.foo = function() { console.log(this.answer); };

    // file2.js
    const obj = require('./file1');
    obj.foo(); // "42"

    // file3.js
    const { foo } = require('./file1');
    foo(); // "undefined"
    ```

    <hr id="arrow-functions" />

    **Q**. I'm using an arrow function for a [virtual](./guide.html#virtuals), [middleware](./middleware.html), [getter](./api.html#schematype_SchemaType-get)/[setter](./api.html#schematype_SchemaType-set), or [method](./guide.html#methods) and the value of `this` is wrong.

    **A**. Arrow functions [handle the `this` keyword much differently than conventional functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this).
    Mongoose getters/setters depend on `this` to give you access to the document that you're writing to, but this functionality does not work with arrow functions. Do **not** use arrow functions for mongoose getters/setters unless do not intend to access the document in the getter/setter.

    ```javascript
    // Do **NOT** use arrow functions as shown below unless you're certain
    // that's what you want. If you're reading this FAQ, odds are you should
    // just be using a conventional function.
    var schema = new mongoose.Schema({
      propWithGetter: {
        type: String,
        get: v => {
          // Will **not** be the doc, do **not** use arrow functions for getters/setters
          console.log(this);
          return v;
        }
      }
    });

    // `this` will **not** be the doc, do **not** use arrow functions for methods
    schema.method.arrowMethod = () => this;
    schema.virtual('virtualWithArrow').get(() => {
      // `this` will **not** be the doc, do **not** use arrow functions for virtuals
      console.log(this);
    });
    ```

    <hr id="type-key">

    **Q**. I have an embedded property named `type` like this:

    ```javascript
    const holdingSchema = new Schema({
      // You might expect `asset` to be an object that has 2 properties,
      // but unfortunately `type` is special in mongoose so mongoose
      // interprets this schema to mean that `asset` is a string
      asset: {
        type: String,
        ticker: String
      }
    });
    ```

    But mongoose gives me a CastError telling me that it can't cast an object
    to a string when I try to save a `Holding` with an `asset` object. Why
    is this?

    ```javascript
    Holding.create({ asset: { type: 'stock', ticker: 'MDB' } }).catch(error => {
      // Cast to String failed for value "{ type: 'stock', ticker: 'MDB' }" at path "asset"
      console.error(error);
    });
    ```

    **A**. The `type` property is special in mongoose, so when you say
    `type: String`, mongoose interprets it as a type declaration. In the
    above schema, mongoose thinks `asset` is a string, not an object. Do
    this instead:

    ```javascript
    const holdingSchema = new Schema({
      // This is how you tell mongoose you mean `asset` is an object with
      // a string property `type`, as opposed to telling mongoose that `asset`
      // is a string.
      asset: {
        type: { type: String },
        ticker: String
      }
    });
    ```

    <hr id="populate_sort_order" />

    **Q**. I'm populating a nested property under an array like the below code:

    ```javascript
      new Schema({
        arr: [{
          child: { ref: 'OtherModel', type: Schema.Types.ObjectId }
        }]
      });
    ```

    `.populate({ path: 'arr.child', options: { sort: 'name' } })` won't sort
    by `arr.child.name`?

    **A**. See [this GitHub issue](https://github.com/Automattic/mongoose/issues/2202). It's a known issue but one that's exceptionally difficult to fix.

    <hr id="model_functions_hanging" />

    **Q**. All function calls on my models hang, what am I doing wrong?

    **A**. By default, mongoose will buffer your function calls until it can
    connect to MongoDB. Read the [buffering section of the connection docs](./connections.html#buffering)
    for more information.

    <hr id="enable_debugging" />

    **Q**. How can I enable debugging?

    **A**. Set the `debug` option to `true`:

    ```javascript
    mongoose.set('debug', true)
    ```

    All executed collection methods will log output of their arguments to your
    console.

    <hr id="callback_never_executes" />

    **Q**. My `save()` callback never executes. What am I doing wrong?

    **A**. All `collection` actions (insert, remove, queries, etc.) are queued
    until the `connection` opens. It is likely that an error occurred while
    attempting to connect. Try adding an error handler to your connection.

    ```javascript
    // if connecting on the default mongoose connection
    mongoose.connect(..);
    mongoose.connection.on('error', handleError);

    // if connecting on a separate connection
    var conn = mongoose.createConnection(..);
    conn.on('error', handleError);
    ```

    If you want to opt out of mongoose's buffering mechanism across your entire
    application, set the global `bufferCommands` option to false:

    ```javascript
    mongoose.set('bufferCommands', false);
    ```

    <hr id="creating_connections" />

    **Q**. Should I create/destroy a new connection for each database operation?

    **A**. No. Open your connection when your application starts up and leave
    it open until the application shuts down.

    <hr id="overwrite-model-error" />

    **Q**. Why do I get "OverwriteModelError: Cannot overwrite .. model once
    compiled" when I use nodemon / a testing framework?

    **A**. `mongoose.model('ModelName', schema)` requires 'ModelName' to be
    unique, so you can access the model by using `mongoose.model('ModelName')`.
    If you put `mongoose.model('ModelName', schema);` in a
    [mocha `beforeEach()` hook](https://mochajs.org/#hooks), this code will
    attempt to create a new model named 'ModelName' before **every** test,
    and so you will get an error. Make sure you only create a new model with
    a given name **once**. If you need to create multiple models with the
    same name, create a new connection and bind the model to the connection.

    ```javascript
    var mongoose = require('mongoose');
    var connection = mongoose.createConnection(..);

    // use mongoose.Schema
    var kittySchema = mongoose.Schema({ name: String });

    // use connection.model
    var Kitten = connection.model('Kitten', kittySchema);
    ```

    <hr id="array-defaults" />

    **Q**. How can I change mongoose's default behavior of initializing an array
    path to an empty array so that I can require real data on document creation?

    **A**. You can set the default of the array to a function that returns `undefined`.
    ```javascript
    const CollectionSchema = new Schema({
      field1: {
        type: [String],
        default: void 0
      }
    });
    ```

    **Q**. How can I initialize an array path to `null`?

    **A**. You can set the default of the array to a function that returns `null`.
    ```javascript
    const CollectionSchema = new Schema({
      field1: {
        type: [String],
        default: () => { return null; }
      }
    });
    ```

    <hr id="aggregate-casting" />

    **Q**. Why does my aggregate $match fail to return the document that my find query
    returns when working with dates?

    **A**. Mongoose does not cast aggregation pipeline stages because with $project,
    $group, etc. the type of a property may change during the aggregation. If you want
    to query by date using the aggregation framework, you're responsible for ensuring
    that you're passing in a valid date.

    <hr id="date_changes" />

    **Q**. Why don't in-place modifications to date objects
    (e.g. `date.setMonth(1);`) get saved?

    ```javascript
    doc.createdAt.setDate(2011, 5, 1);
    doc.save(); // createdAt changes won't get saved!
    ```

    **A**. Mongoose currently doesn't watch for in-place updates to date
    objects. If you have need for this feature, feel free to discuss on
    [this GitHub issue](https://github.com/Automattic/mongoose/issues/3738).
    There are several workarounds:

    ```javascript
    doc.createdAt.setDate(2011, 5, 1);
    doc.markModified('createdAt');
    doc.save(); // Works

    doc.createdAt = new Date(2011, 5, 1).setHours(4);
    doc.save(); // Works
    ```

    <hr id="parallel_saves" />

    **Q**. Why does calling `save()` multiple times on the same document in parallel only let
    the first save call succeed and return ParallelSaveErrors for the rest?

    **A**. Due to the asynchronous nature of validation and middleware in general, calling
    `save()` multiple times in parallel on the same doc could result in conflicts. For example,
    validating, and then subsequently invalidating the same path.

    <hr id="objectid-validation" />

    **Q**. Why is **any** 12 character string successfully cast to an ObjectId?

    **A**. Technically, any 12 character string is a valid [ObjectId](https://docs.mongodb.com/manual/reference/bson-types/#objectid).
    Consider using a regex like `/^[a-f0-9]{24}$/` to test whether a string is exactly 24 hex characters.

    <hr id="slow-localhost" />

    **Q**. I'm connecting to `localhost` and it takes me nearly 1 second to connect. How do I fix this?

    **A**. The underlying MongoDB driver defaults to looking for IPv6 addresses, so the most likely cause is that your `localhost` DNS mapping isn't configured to handle IPv6. Use `127.0.0.1` instead of `localhost` or use the `family` option as shown in the [connection docs](https://mongoosejs.com/docs/connections.html#options).

    ```javascript
    // One alternative is to bypass 'localhost'
    mongoose.connect('mongodb://127.0.0.1:27017/test');
    // Another option is to specify the `family` option, which tells the
    // MongoDB driver to only look for IPv4 addresses rather than IPv6 first.
    mongoose.connect('mongodb://localhost:27017/test', { family: 4 });
    ```

    <hr id="map-keys-strings" />

    **Q**. Why do keys in Mongoose Maps have to be strings?

    **A**. Because the Map eventually gets stored in MongoDB where the keys must be strings.

    <hr id="add_something" />

    **Something to add?**

    If you'd like to contribute to this page, please
    [visit it](https://github.com/Automattic/mongoose/tree/master/docs/faq.jade)
    on github and use the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button to send a pull request.
